<?php
 namespace templateMethod;

/**
 * 模板方法模式的具体角色和职责
 * 1. 抽象父类，也可以叫模板类、骨架类：提供一个业务逻辑的模板方法(公共方法)和公共流程
 * 2. 实现具体子类子类，继承抽象父类，并实现抽象父类中的抽象方法，完成具体逻辑
 * 3. 客户端调用
 */

// 以订单流程为例，查看库存-->支付--->发货--->通知
// 1. 抽象父类，定义业务逻辑的模板方法(公共方法)和公共流程以及需要去子类中实现的抽象方法
abstract class OrderProcessTemplate
{
    protected string $orderType;
    public function processOrder(): void
    {
        $this->checkStock();
        $this->pay();
        $this->deliver();
        $this->notify();
    }
    // 查看库存
    private function checkStock(): void
    {
        echo "查看库存-->";
    }
    // 支付
    abstract protected function pay(): void;
    // 发货
    abstract protected function deliver(): void;
    // 通知
    private function notify(): void
    {
        echo "订单完成，请及时通知客户";
    }
}

// 2. 实现具体子类，继承抽象父类，并实现抽象父类中的抽象方法，完成具体逻辑
// 这里使用实物商品和虚拟商品为例
class PhysicalGoodsOrder extends OrderProcessTemplate
{
    protected function pay(): void
    {
        echo '微信支付-->';
    }
    protected function deliver(): void
    {
        echo "实物顺丰物流发货-->";
    }
}
class VirtualGoodsOrder extends OrderProcessTemplate
{
    protected function pay(): void
    {
        echo '支付宝支付-->';
    }
    protected function deliver(): void
    {
        echo "虚拟物品邮件发货-->";
    }
}

// 测试
$physicalGoodsOrder = new PhysicalGoodsOrder();
$physicalGoodsOrder->processOrder();
echo "\n";
echo "-------------------------\n";
$virtualGoodsOrder = new VirtualGoodsOrder();
$virtualGoodsOrder->processOrder();